﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Netfraction.Network.Protocol
{
    public abstract class ProtocolMessageActionHandler
    {
        protected List<string> mParameterCodes;
        protected List<RemoteMachine.ConnectionState> mSupportedConnectionStates;

        protected ProtocolMessageActionHandler()
        {
            mParameterCodes = new List<string>();
            mSupportedConnectionStates = new List<RemoteMachine.ConnectionState>();
        }

        public abstract string ProtocolActionCode { get; }

        public List<RemoteMachine.ConnectionState> SupportedConnectionStates
        {
            get { return mSupportedConnectionStates; }
        }

        public virtual bool HandleProtocolMessage(RemoteMachine.Node node, ProtocolMessage message, IEnumerable<ProtocolFeature> extensionFeatures)
        {
            return false;
        }

        public virtual object HandleMessageExtension(RemoteMachine.Node node, ProtocolMessage message, params object[] args)
        {
            return null;
        }

        protected object CallMessageExtensions(RemoteMachine.Node node, ProtocolMessage message, IEnumerable<ProtocolFeature> extenders, int extensionType, params object[] args)
        {
            object o = null;
            foreach (ProtocolFeature feat in extenders)
            {
                o = feat.HandleExtensionMessage(node, message, extensionType, args);
                if (o != null)
                    break;
            }
            return o;
        }

        /// <summary>
        /// Allows each handler to seperate parameters into appropriate name/value pairs
        /// </summary>
        /// <parameter name="message"></parameter>
        /// <returns></returns>
        //protected abstract List<ProtocolParameter> DecodeParameters(List<ProtocolParameter> message);
        protected List<ProtocolParameter> DecodeParameters(List<ProtocolParameter> parameters)
        {
            foreach (string code in mParameterCodes)
            {
                for (int i = 0; i < parameters.Count; i++)
                {
                    // we don't want this to run twice on params that are already split, but we also need to allow for multiple params with the same code
                    // so, by checking if this param has a parameterCode set, we are able to stop the duplication
                    // an example error of not doing this is the following message:
                    // BINF AIAA IDPDIZIRLXPW53WZYQVBAJ56TLPZAMFSTIPQLBIKA PDPRU37JWBCO6HLWS3PP4SNOR3IBTBUDIWK5IP6XY
                    // Because the ID message has PD in the next two characters, the code would split it a second time, and lead to a bug.
                    if (string.IsNullOrEmpty(parameters[i].ParameterCode) && parameters[i].ParameterValue.StartsWith(code, StringComparison.Ordinal))
                        parameters[i] = ProtocolParameter.Split(parameters[i], code);
                }
            }
            return parameters;
        }

        /// <summary>
        /// Returns a value indicating if the ProtocolMessageActionHandler supports the given ProtocolMessage
        /// </summary>        
        protected bool IsSupportedConnectionState(RemoteMachine.Node node)
        {
            return node.Connection != null ? mSupportedConnectionStates.Contains(node.Connection.State) : false;
        }

        /*
        /// <summary>
        /// Handle the given Hub ProtocolMessage
        /// </summary>
        public abstract bool HandleHubMessage(Hub hub, ProtocolMessage protocolMessage);

        /// <summary>
        /// Handle the given Client ProtocolMessage
        /// </summary>
        public abstract bool HandlePeerMessage(Peer peer, ProtocolMessage protocolMessage);*/
    }
}
